<template>
  <div>
    <CompositeProp
    name="checkers"
    :prop-path="propPath"
    :schema="schema"
    :ui-schema="uiSchema"
    :data="widgetExtendedPropsData"
    :pages="pages"
    :widgets="widgets"
    @change="onChangePropValue"
    @enter="onEnterProp"
    @edit-custom="onEditCustomProp"
    @edit-file="onEditFile"
    @edit-richtext="onEditRichtext"
    ></CompositeProp>

    <a-modal
      title="选择资源文件"
      v-model:visible="isSelectingResourceFile"
      @ok="onConfirmSelectResourceFile"
      @cancel="onCancelSelectResourceFile"
      okText="确定"
      cancelText="取消"
    >
      <a-select
        v-model:value="selectedResourceFileName"
        style="width: 100%"
        placeholder="请选择"
      >
        <a-select-option
          v-for="(filename, i) in etbResourceFiles"
          :key="i"
          :value="filename"
        >{{ filename }}</a-select-option>
      </a-select>
    </a-modal>

    <a-modal
      title="选择资源文件"
      v-model:visible="isCustomPropSelectingResourceFiles"
      @ok="onConfirmCustomPropSelectResourceFiles"
      @cancel="onCancelCustomPropSelectResourceFiles"
      okText="确定"
      cancelText="取消"
    >
      <a-select
        v-if="isCustomPropPickMultipleFiles"
        v-model:value="customPropSelectedResourceFileNames"
        mode="multiple"
        style="width: 100%"
        placeholder="请选择"
      >
        <a-select-option
          v-for="(filename, i) in etbResourceFiles"
          :key="i"
          :value="filename"
        >{{ filename }}</a-select-option>
      </a-select>
      <a-select
        v-else
        v-model:value="customPropSelectedResourceFileName"
        style="width: 100%"
        placeholder="请选择"
      >
        <a-select-option
          v-for="(filename, i) in etbResourceFiles"
          :key="i"
          :value="filename"
        >{{ filename }}</a-select-option>
      </a-select>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { Ref, ref } from 'vue';
import { message as AntdMessage } from 'ant-design-vue';
import type { WidgetExtendedPropMeta, WidgetOption, ObjectSchema, CustomPropSchema } from '@learnware/wpe';
import { CompositeProp, widgetOptionsConverter } from '@learnware/wpe';
import packageJson from '../package.json';
import options from '../src/options.json';
import widgetExtendedPropsData from '../src/init.json';
import translations from '../src/_locales/zh-CN/package.json';
import { translateWidgetMeta, updateWidgetPropValueByPropPath, getWidgetPropValueByPropPath } from './utils';

interface IWidgetIdAndName { id: string; name: string; };
type IWidgetPropPath = Array<string | number>;

const translatedOptions = translateWidgetMeta(options, 'options', translations);

const propPath: Ref<WidgetExtendedPropMeta[]> = ref([]);
const pages: { id: string, name: string }[] = [];
const widgets: Ref<IWidgetIdAndName[]> = ref([]);
const { schema, uiSchema } = widgetOptionsConverter.convertWidgetOptions(
  translatedOptions as WidgetOption[],
  packageJson.widgetProperties.name,
  translations.package.displayName,
  translations.package.description,
);

function onEnterProp(prop: WidgetExtendedPropMeta) {
  propPath.value.push({ name: prop.name, type: prop.type, title: prop.title });
}

const readerFrame = document.querySelector('#learnware-renderer > iframe') as HTMLIFrameElement;
function onChangePropValue({ propPath, value }: { propPath: IWidgetPropPath, value: any }) {

  updateWidgetPropValueByPropPath(widgetExtendedPropsData, schema, propPath, value);

  const myWidgets = widgets.value.reduce((items, item) => {
    if (item.id.indexOf(packageJson.widgetProperties.name) === 0) {
      items.push({ id: item.id, name: item.name });
    }
    return items;
  }, [] as Array<IWidgetIdAndName>);
  
  const [propName] = propPath;
  myWidgets.forEach((item) => {
    readerFrame.contentWindow?.postMessage({
      type: 'invokeWidgetMethod',
      data: {
        widgetId: item.id,
        methodName: 'refreshUI',
        methodArgs: [{ [propName]: widgetExtendedPropsData[propName] }],
      }
    }, '*');
  });
}

/**
 * 响应编辑自定义属性事件，加载自定义属性编辑界面。
 */
const customPropEditor = document.querySelector('#custom-widget-prop-editor') as HTMLElement;
const customPropEditorFrame = document.querySelector('#custom-widget-prop-editor > iframe') as HTMLIFrameElement;
let editingCustomPropName = '';
function onEditCustomProp({ propPath }: { propPath: IWidgetPropPath }) {
  if (propPath.length !== 1) {
    AntdMessage.error('自定义属性仅能用在根属性上！');
    return;
  }

  customPropEditor.style.display = 'block';

  const fullPath = `${window.location.origin}/etb/OEBPS`;
  customPropEditorFrame.contentWindow?.postMessage({
    type: 'updateEnv',
    data: {
      pageWidgets: JSON.parse(JSON.stringify(widgets.value.map(w => ({
        id: w.id,
        name: w.name,
        widgetType: w.id.split('-')[0],
      })))),
      pages,
      fullPath,
    }
  }, '*');

  const [propName] = propPath;
  const propSchema = (schema as ObjectSchema).properties[propName] as CustomPropSchema;
  customPropEditorFrame.contentWindow?.postMessage({
    type: 'loadWidgetPropEditor',
    data: {
      scriptUrl: `${fullPath}/controls/${packageJson.widgetProperties.name}/${propSchema.script}`,
      cssUrl: propSchema.css ? `${fullPath}/controls/${packageJson.widgetProperties.name}/${propSchema.css}` : '',
      widgetName: packageJson.widgetProperties.name,
      propName,
      propValue: JSON.parse(JSON.stringify(widgetExtendedPropsData[propName])),
      basicPropsValue: {
        width: widgetExtendedPropsData.width,
        height: widgetExtendedPropsData.height,
        name: translations.package.displayName,
      },
      extendedPropsValue: JSON.parse(JSON.stringify(widgetExtendedPropsData))
    }
  }, '*');

  editingCustomPropName = propName as string;
}

// webpack 开发环境读取学件资源目录文件列表，并将列表值赋值给 window.ETB_RESOURCE_FILES
declare global {
  interface Window {
    ETB_RESOURCE_FILES: string[];
  }
}

const etbResourceFiles = window.ETB_RESOURCE_FILES;
const selectedResourceFileName = ref('');
const isSelectingResourceFile = ref(false);
let editingFilePropPath: IWidgetPropPath | null = null;
function onEditFile({ propPath }: { propPath: IWidgetPropPath }) {
  editingFilePropPath = propPath;
  const currentValue = getWidgetPropValueByPropPath(widgetExtendedPropsData, schema, propPath);
  if (typeof currentValue === 'string' && currentValue.indexOf('resources/') === 0) {
    selectedResourceFileName.value = currentValue.split('/').pop() || '';
  } else {
    selectedResourceFileName.value = '';
  }
  isSelectingResourceFile.value = true;
}
function onConfirmSelectResourceFile() {
  if (editingFilePropPath && selectedResourceFileName.value) {
    updateWidgetPropValueByPropPath(
      widgetExtendedPropsData,
      schema,
      editingFilePropPath,
      `resources/${selectedResourceFileName.value}`,
    );
  }
  isSelectingResourceFile.value = false;
}
function onCancelSelectResourceFile() {
  isSelectingResourceFile.value = false;
}

const customPropSelectedResourceFileNames = ref([] as string[]);
const customPropSelectedResourceFileName = ref('');
const isCustomPropSelectingResourceFiles = ref(false);
const isCustomPropPickMultipleFiles = ref(false);
let customPropFilePropPath = '';
function onCustomPropPickFile(propPath: string, propValue: string[], multiple: boolean) {
  customPropFilePropPath = propPath;
  isCustomPropPickMultipleFiles.value = multiple;
  if (multiple) {
    customPropSelectedResourceFileNames.value = propValue;
  } else {
    customPropSelectedResourceFileName.value = propValue[0] || '';
  }
  isCustomPropSelectingResourceFiles.value = true;
}
function onConfirmCustomPropSelectResourceFiles() {
  customPropEditorFrame.contentWindow?.postMessage({
    type: 'changeFilePropValue',
    data: {
      propPath: customPropFilePropPath,
      propValue: isCustomPropPickMultipleFiles ?
        customPropSelectedResourceFileNames.value.map(v => `resources/${v}`) :
        [`resources/${customPropSelectedResourceFileName.value}`]
    }
  }, '*');
  isCustomPropSelectingResourceFiles.value = false;
}
function onCancelCustomPropSelectResourceFiles() {
  isCustomPropSelectingResourceFiles.value = false;
}

const richtextEditor = document.querySelector('#richtext-editor') as HTMLElement;
const richtextEditorFrame = document.querySelector('#richtext-editor > iframe') as HTMLIFrameElement;
let editingRichtextPropPath: IWidgetPropPath | null = null;
function onEditRichtext({ propPath }: { propPath: IWidgetPropPath }) {
  editingRichtextPropPath = propPath;

  richtextEditor.style.display = 'block';

  let childData = widgetExtendedPropsData;
  for (let i = 0; i < propPath.length; i++) {
    if (!childData) return;
    childData = childData[propPath[i]];
  }
  richtextEditorFrame.contentWindow?.postMessage({ type: 'setContent', data: { content: childData } }, '*');
}

window.addEventListener('message', (evt) => {
  console.log('received message of type ', evt.data?.type, ': ', evt.data);
  if (evt.data?.type === 'reader:pageRendered') {
    if (evt.data?.data?.widgets) {
      widgets.value = evt.data.data.widgets.map((w) => ({ id: w.itemId, name: w.displayName }));
    }
  } else if (evt.data?.type === 'customWidgetPropEditor:submit') {
    if (customPropEditor) {
      customPropEditor.style.display = 'none';
      onChangePropValue({ propPath: [editingCustomPropName], value: evt.data.data});
    }
  } else if (evt.data?.type === 'customWidgetPropEditor:cancel') {
    if (customPropEditor) {
      customPropEditor.style.display = 'none';
    }
  } else if (evt.data?.type === 'customWidgetPropEditor:pickFile') {
    onCustomPropPickFile(evt.data?.data?.propPath, evt.data?.data?.propValue, evt.data?.data?.multiple);
  } else if (evt.data?.type === 'richtextEditor:submit') {
    if (richtextEditor) {
      richtextEditor.style.display = 'none';
      if (editingRichtextPropPath) {
        onChangePropValue({ propPath: editingRichtextPropPath, value: evt.data.data.content });
      }
    }
  } else if (evt.data?.type === 'richtextEditor:cancel') {
    if (richtextEditor) {
      richtextEditor.style.display = 'none';
    }
  }
});

</script>